#include "head.h"

int send_small_file(int net_fd,int file_fd,int file_size)
{
    int cur_size=0;
    int send_size=0;
    self_defined_pro_t *sdp=(self_defined_pro_t *)calloc(1,sizeof(self_defined_pro_t));

    while(send_size<file_size)
    {
        cur_size=(file_size-send_size)<1024?file_size-send_size:1024;
        bzero(sdp->message,sizeof(sdp->message));
        read(file_fd,sdp->message,cur_size);

        int ret =send(net_fd,sdp->message,cur_size,MSG_NOSIGNAL);
        if(ret<=0){
            return ret;
        }
        send_size+=cur_size;

    }
    free(sdp);
    return file_size;
}


int send_large_file(int net_fd,int file_fd,int offset,int file_size)
{
    off_t send_size =0;
    off_t cur_size=0;

    while(send_size<file_size)
    {
        if(file_size-send_size<4096)
        {
            cur_size=file_size-send_size;

        }
        else
        {
            cur_size=4096;
        }

        char * p=(char *) mmap(NULL,cur_size,PROT_READ|PROT_WRITE,MAP_SHARED,file_fd,0);

        int ret=send(net_fd,p,cur_size,MSG_NOSIGNAL);
        if(ret<=0)
        {
            return ret;
        }
        munmap(p,cur_size);

        send_size+=cur_size;
    }
    return file_size;
}


int server_download(int net_fd,self_defined_pro_t *msg)
{   
    //接收文件名
    char *username=strtok(msg->message,"=");
    username=strtok(NULL,"&");
    char *path=strtok(NULL,"=");
    path=strtok(NULL,"&");
    char *filename=strtok(NULL,"=");
    filename=strtok(NULL,"&");
    // 获得当前路径
    char cwd[200] = {0};
    getcwd(cwd, sizeof(cwd));

    // 拼接路径
    strcat(cwd, "/");
    strcat(cwd, username);
    if(strlen(path) != 1 ){
        strcat(cwd, path);
    }
    strcat(cwd, "/");
    strcat(cwd, filename);

    // 先去判断是否有同名文件, 如果有, 观察是否需要走断点续传逻辑: same_file\函数
    struct dirent *entry;
    char directory[200]={0};
    getcwd(directory, sizeof(directory));
    strcat(directory, "/");
    strcat(directory, username);
    if(strlen(path) != 1 ){
        strcat(directory, path);
    }

    DIR *dir = opendir(directory);

    int flag=0;//判断是否存在同名文件 1为存在 0为不存在直接传
    while ((entry = readdir(dir)) !=NULL) {
        if (strcmp(entry->d_name, filename) == 0) {
            flag = 1; // 找到同名文件
            break; // 跳出循环
        }
    }

    closedir(dir);

    self_defined_pro_t *sdp=(self_defined_pro_t *)calloc(1,sizeof(self_defined_pro_t));
    strcat(directory,"/");
    strcat(directory,filename);
    if(flag==1)
    {
        //cmd=200 表示存在
        int file_fd=open(directory,O_RDWR);
        struct stat stat_file;
        fstat(file_fd,&stat_file);
        int file_size=stat_file.st_size;
        sdp->cmd=200;
        sdp->para_num=file_size;//文件在服务端大小
        send(net_fd,sdp,sizeof(self_defined_pro_t),MSG_NOSIGNAL);
        //比较文件大小 决定使用全部发送还是断点续传
        recv(net_fd,sdp,sizeof(self_defined_pro_t),MSG_WAITALL);
        int file_size_client=sdp->cmd;
        if(file_size_client<0)
        {
            //完全发送
            
            send(net_fd,&file_size,sizeof(int),MSG_NOSIGNAL);
            if(file_size>=1000000)
            {
                //大文件传递
                send_large_file(net_fd,file_fd,0,file_size);
            }
            else{
                //小文件传递
                send_small_file(net_fd,file_fd,file_size);
            }
        }else{
            //断点续传，从file_size—client位置开始发送
            off_t client_file_size =file_size_client ;
            sendfile(net_fd, file_fd, &client_file_size, file_size-client_file_size);
        }
        //判断文件大小 区分发送方式

    }else{

        //发送cmd=210 告诉客户端无同名文件
        sdp->cmd=210;
        sdp->para_num=0;//文件在服务端大小
        send(net_fd,sdp,sizeof(self_defined_pro_t),MSG_NOSIGNAL);
    }
    return 0;
}

